﻿using System;
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
using NetTopologySuite.Utilities;

namespace NetTopologySuite.LinearReferencing
{
	public class LocationIndexOfPoint
	{
		public static LinearLocation IndexOf(IGeometry linearGeom, Coordinate inputPt)
		{
			return new LocationIndexOfPoint(linearGeom).IndexOf(inputPt);
		}

		public static LinearLocation IndexOfAfter(IGeometry linearGeom, Coordinate inputPt, LinearLocation minIndex)
		{
			return new LocationIndexOfPoint(linearGeom).IndexOfAfter(inputPt, minIndex);
		}

		public LocationIndexOfPoint(IGeometry linearGeom)
		{
			this._linearGeom = linearGeom;
		}

		public LinearLocation IndexOf(Coordinate inputPt)
		{
			return this.IndexOfFromStart(inputPt, null);
		}

		public LinearLocation IndexOfAfter(Coordinate inputPt, LinearLocation minIndex)
		{
			if (minIndex == null)
			{
				return this.IndexOf(inputPt);
			}
			LinearLocation endLocation = LinearLocation.GetEndLocation(this._linearGeom);
			if (endLocation.CompareTo(minIndex) <= 0)
			{
				return endLocation;
			}
			LinearLocation linearLocation = this.IndexOfFromStart(inputPt, minIndex);
			Assert.IsTrue(linearLocation.CompareTo(minIndex) >= 0, "computed location is before specified minimum location");
			return linearLocation;
		}

		private LinearLocation IndexOfFromStart(Coordinate inputPt, LinearLocation minIndex)
		{
			double num = double.MaxValue;
			int componentIndex = 0;
			int segmentIndex = 0;
			double segmentFraction = -1.0;
			LineSegment lineSegment = new LineSegment();
			LinearIterator linearIterator = new LinearIterator(this._linearGeom);
			while (linearIterator.HasNext())
			{
				if (!linearIterator.IsEndOfLine)
				{
					lineSegment.P0 = linearIterator.SegmentStart;
					lineSegment.P1 = linearIterator.SegmentEnd;
					double num2 = lineSegment.Distance(inputPt);
					double num3 = lineSegment.SegmentFraction(inputPt);
					int componentIndex2 = linearIterator.ComponentIndex;
					int vertexIndex = linearIterator.VertexIndex;
					if (num2 < num && (minIndex == null || minIndex.CompareLocationValues(componentIndex2, vertexIndex, num3) < 0))
					{
						componentIndex = componentIndex2;
						segmentIndex = vertexIndex;
						segmentFraction = num3;
						num = num2;
					}
				}
				linearIterator.Next();
			}
			if (num == 1.7976931348623157E+308)
			{
				return new LinearLocation(minIndex);
			}
			return new LinearLocation(componentIndex, segmentIndex, segmentFraction);
		}

		private readonly IGeometry _linearGeom;
	}
}
